/**
 * WebSocket封装工具
 */

/**
 * WebSocket状态枚举
 */
export const WebSocketStatus = {
  CONNECTING: 'CONNECTING',
  OPEN: 'OPEN',
  CLOSING: 'CLOSING',
  CLOSED: 'CLOSED'
} as const;

export type WebSocketStatusType = typeof WebSocketStatus[keyof typeof WebSocketStatus];

/**
 * 消息类型定义
 */
export interface WebSocketMessage {
  type: string;
  data: any;
  timestamp?: number;
  id?: string;
}

/**
 * 事件回调类型
 */
export type WebSocketEventHandler = (data: any) => void;

/**
 * 连接选项
 */
export interface WebSocketOptions {
  url: string;
  protocols?: string | string[];
  reconnectInterval?: number;
  maxReconnectAttempts?: number;
  heartbeatInterval?: number;
  heartbeatMessage?: string;
  timeout?: number;
  debug?: boolean;
}

/**
 * WebSocket管理器类
 */
export class WebSocketManager {
  private ws: WebSocket | null = null;
  private options: WebSocketOptions;
  private status: WebSocketStatusType = WebSocketStatus.CLOSED;
  private reconnectAttempts = 0;
  private reconnectTimer: number | null = null;
  private heartbeatTimer: number | null = null;
  private eventHandlers = new Map<string, Set<WebSocketEventHandler>>();
  private messageQueue: WebSocketMessage[] = [];
  private isManualClose = false;

  constructor(options: WebSocketOptions) {
    this.options = {
      reconnectInterval: 3000,
      maxReconnectAttempts: 5,
      heartbeatInterval: 30000,
      heartbeatMessage: 'ping',
      timeout: 10000,
      debug: false,
      ...options
    };
  }

  /**
   * 连接WebSocket
   */
  connect(): Promise<void> {
    return new Promise((resolve, reject) => {
      if (this.status === WebSocketStatus.OPEN || this.status === WebSocketStatus.CONNECTING) {
        resolve();
        return;
      }

      this.isManualClose = false;
      this.status = WebSocketStatus.CONNECTING;

      try {
        this.ws = new WebSocket(this.options.url, this.options.protocols);
        
        // 设置超时
        const timeout = setTimeout(() => {
          if (this.status === WebSocketStatus.CONNECTING) {
            this.ws?.close();
            reject(new Error('连接超时'));
          }
        }, this.options.timeout);

        this.ws.onopen = (event) => {
          clearTimeout(timeout);
          this.status = WebSocketStatus.OPEN;
          this.reconnectAttempts = 0;
          this.log('WebSocket连接成功');
          
          // 发送队列中的消息
          this.sendQueuedMessages();
          
          // 开始心跳
          this.startHeartbeat();
          
          this.emit('open', event);
          resolve();
        };

        this.ws.onmessage = (event) => {
          this.handleMessage(event);
        };

        this.ws.onclose = (event) => {
          clearTimeout(timeout);
          this.status = WebSocketStatus.CLOSED;
          this.stopHeartbeat();
          this.log('WebSocket连接关闭', event);
          
          this.emit('close', event);
          
          // 如果不是手动关闭，尝试重连
          if (!this.isManualClose && this.reconnectAttempts < this.options.maxReconnectAttempts!) {
            this.scheduleReconnect();
          }
        };

        this.ws.onerror = (event) => {
          clearTimeout(timeout);
          this.log('WebSocket错误', event);
          this.emit('error', event);
          reject(event);
        };

      } catch (error) {
        this.status = WebSocketStatus.CLOSED;
        reject(error);
      }
    });
  }

  /**
   * 断开连接
   */
  disconnect(): void {
    this.isManualClose = true;
    this.stopHeartbeat();
    this.clearReconnectTimer();
    
    if (this.ws) {
      this.ws.close();
      this.ws = null;
    }
    
    this.status = WebSocketStatus.CLOSED;
  }

  /**
   * 发送消息
   */
  send(message: WebSocketMessage | string): boolean {
    if (this.status !== WebSocketStatus.OPEN) {
      this.log('WebSocket未连接，消息已加入队列');
      this.messageQueue.push(typeof message === 'string' ? { type: 'message', data: message } : message);
      return false;
    }

    try {
      const messageStr = typeof message === 'string' ? message : JSON.stringify(message);
      this.ws!.send(messageStr);
      this.log('发送消息', message);
      return true;
    } catch (error) {
      this.log('发送消息失败', error);
      return false;
    }
  }

  /**
   * 订阅事件
   */
  on(event: string, handler: WebSocketEventHandler): void {
    if (!this.eventHandlers.has(event)) {
      this.eventHandlers.set(event, new Set());
    }
    this.eventHandlers.get(event)!.add(handler);
  }

  /**
   * 取消订阅事件
   */
  off(event: string, handler?: WebSocketEventHandler): void {
    if (!this.eventHandlers.has(event)) return;
    
    if (handler) {
      this.eventHandlers.get(event)!.delete(handler);
    } else {
      this.eventHandlers.delete(event);
    }
  }

  /**
   * 获取连接状态
   */
  getStatus(): WebSocketStatusType {
    return this.status;
  }

  /**
   * 是否已连接
   */
  isConnected(): boolean {
    return this.status === WebSocketStatus.OPEN;
  }

  /**
   * 获取重连次数
   */
  getReconnectAttempts(): number {
    return this.reconnectAttempts;
  }

  /**
   * 处理接收到的消息
   */
  private handleMessage(event: MessageEvent): void {
    try {
      let message: WebSocketMessage;
      
      if (typeof event.data === 'string') {
        try {
          message = JSON.parse(event.data);
        } catch {
          message = { type: 'message', data: event.data };
        }
      } else {
        message = { type: 'message', data: event.data };
      }

      // 添加时间戳
      if (!message.timestamp) {
        message.timestamp = Date.now();
      }

      this.log('接收消息', message);

      // 触发消息事件
      this.emit('message', message);
      
      // 触发特定类型事件
      if (message.type) {
        this.emit(message.type, message.data);
      }

      // 处理心跳响应
      if (message.type === 'pong' || message.data === 'pong') {
        this.log('收到心跳响应');
      }

    } catch (error) {
      this.log('处理消息失败', error);
    }
  }

  /**
   * 发送队列中的消息
   */
  private sendQueuedMessages(): void {
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift()!;
      this.send(message);
    }
  }

  /**
   * 开始心跳
   */
  private startHeartbeat(): void {
    if (this.options.heartbeatInterval && this.options.heartbeatInterval > 0) {
      this.heartbeatTimer = setInterval(() => {
        if (this.status === WebSocketStatus.OPEN) {
          this.send(this.options.heartbeatMessage!);
        }
      }, this.options.heartbeatInterval);
    }
  }

  /**
   * 停止心跳
   */
  private stopHeartbeat(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 安排重连
   */
  private scheduleReconnect(): void {
    this.reconnectAttempts++;
    this.log(`准备第${this.reconnectAttempts}次重连，${this.options.reconnectInterval}ms后执行`);
    
    this.reconnectTimer = setTimeout(() => {
      this.log(`执行第${this.reconnectAttempts}次重连`);
      this.connect().catch((error) => {
        this.log('重连失败', error);
      });
    }, this.options.reconnectInterval);
  }

  /**
   * 清除重连定时器
   */
  private clearReconnectTimer(): void {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
  }

  /**
   * 触发事件
   */
  private emit(event: string, data?: any): void {
    const handlers = this.eventHandlers.get(event);
    if (handlers) {
      handlers.forEach(handler => {
        try {
          handler(data);
        } catch (error) {
          this.log(`事件处理器执行失败: ${event}`, error);
        }
      });
    }
  }

  /**
   * 日志输出
   */
  private log(message: string, data?: any): void {
    if (this.options.debug) {
      console.log(`[WebSocket] ${message}`, data || '');
    }
  }
}

/**
 * WebSocket连接池管理器
 */
export class WebSocketPool {
  private connections = new Map<string, WebSocketManager>();

  /**
   * 创建或获取连接
   */
  getConnection(key: string, options: WebSocketOptions): WebSocketManager {
    if (!this.connections.has(key)) {
      const connection = new WebSocketManager(options);
      this.connections.set(key, connection);
    }
    return this.connections.get(key)!;
  }

  /**
   * 关闭指定连接
   */
  closeConnection(key: string): void {
    const connection = this.connections.get(key);
    if (connection) {
      connection.disconnect();
      this.connections.delete(key);
    }
  }

  /**
   * 关闭所有连接
   */
  closeAllConnections(): void {
    this.connections.forEach(connection => {
      connection.disconnect();
    });
    this.connections.clear();
  }

  /**
   * 获取所有连接
   */
  getAllConnections(): Map<string, WebSocketManager> {
    return new Map(this.connections);
  }
}

/**
 * WebSocket组合式函数
 */
export function useWebSocket(options: WebSocketOptions) {
  const connection = new WebSocketManager(options);

  /**
   * 连接
   */
  const connect = () => connection.connect();

  /**
   * 断开连接
   */
  const disconnect = () => connection.disconnect();

  /**
   * 发送消息
   */
  const send = (message: WebSocketMessage | string) => connection.send(message);

  /**
   * 订阅事件
   */
  const on = (event: string, handler: WebSocketEventHandler) => connection.on(event, handler);

  /**
   * 取消订阅
   */
  const off = (event: string, handler?: WebSocketEventHandler) => connection.off(event, handler);

  /**
   * 获取状态
   */
  const getStatus = () => connection.getStatus();

  /**
   * 是否已连接
   */
  const isConnected = () => connection.isConnected();

  return {
    connect,
    disconnect,
    send,
    on,
    off,
    getStatus,
    isConnected
  };
}

/**
 * 全局WebSocket连接池实例
 */
export const wsPool = new WebSocketPool();

/**
 * WebSocket工具函数
 */
export const wsUtils = {
  /**
   * 创建WebSocket连接
   */
  create: (options: WebSocketOptions) => new WebSocketManager(options),

  /**
   * 创建带重连的WebSocket连接
   */
  createWithReconnect: (options: WebSocketOptions & { reconnectInterval?: number; maxReconnectAttempts?: number }) => {
    return new WebSocketManager({
      reconnectInterval: 3000,
      maxReconnectAttempts: 5,
      ...options
    });
  },

  /**
   * 创建心跳WebSocket连接
   */
  createWithHeartbeat: (options: WebSocketOptions & { heartbeatInterval?: number; heartbeatMessage?: string }) => {
    return new WebSocketManager({
      heartbeatInterval: 30000,
      heartbeatMessage: 'ping',
      ...options
    });
  },

  /**
   * 检查WebSocket支持
   */
  isSupported: (): boolean => {
    return typeof WebSocket !== 'undefined';
  },

  /**
   * 获取WebSocket状态文本
   */
  getStatusText: (status: WebSocketStatusType): string => {
    const statusMap = {
      [WebSocketStatus.CONNECTING]: '连接中',
      [WebSocketStatus.OPEN]: '已连接',
      [WebSocketStatus.CLOSING]: '关闭中',
      [WebSocketStatus.CLOSED]: '已关闭'
    };
    return statusMap[status] || '未知状态';
  }
};
